BZOJ3033 太鼓达人 <欧拉回路>

Problem

太鼓达人


Description

七夕祭上, 牵着 的手,在明亮的灯光和欢乐的气氛中愉快地穿行。这时,在前面忽然出现了一台太鼓达人机台,而在机台前坐着的是刚刚被精英队伍成员 _ 拯救出来的的 。看到两人对太鼓达人产生了兴趣, 果断闪人,于是 拿起鼓棒准备挑战。然而即使是在普通难度下, 的路人本性也充分地暴露了出来。一曲终了,不但没有过关,就连鼓都不灵了。 十分过意不去,决定帮助工作人员修鼓。
鼓的主要元件是 个围成一圈的传感器。每个传感器都有开和关两种工作状态,分别用 表示。显然,从不同的位置出发沿顺时针方向连续检查 个传感器可以得到 个长度为 串。 知道这 串应该是互不相同的。而且鼓的设计很精密, 会取到可能的最大值。现在 已经了解到了K的值,他希望你求出 的值,并给出字典序最小的传感器排布方案。

Input

一个整数

Output

一个整数 和一个二进制串,由一个空格分隔。表示可能的最大的 以及字典序最小的排布方案,字符 表示关, 表示开。你输出的串的第一个字和最后一个字是相邻的。

Sample Input

1
3

Sample Output

1
8 00010111

Hint

得到的 串分别是 。注意前后是相邻的。长度为 的二进制串总共只有 种,所以 一定是可能的最大值。
对于全部测试点,

Source

Poetize2

标签:欧拉回路

Solution

位二进制数看成点, 位二进制数看成边,连接 两点的边权就是
例如 时,边 的权为 ,整个图如下:




(转载自 Clove_unique 的博客)
显然每个点的出度和入度均为 ,一定存在欧拉回路,而欧拉回路一定会经过所有的边,即凑出所有 位二进制数。于是第一问答案为 ,第二问在图上找出字典序最小的欧拉回路即可。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <bits/stdc++.h>
using namespace std;
template <class T> inline void read(T &x) {
x = 0; int c = getchar(), f = 1;
for (; !isdigit(c); c = getchar()) if (c == 45) f = -1;
for (; isdigit(c); c = getchar()) (x *= 10) += f*(c-'0');
}
int n, ans[2048]; bool mrk[2048];
bool DFS(int stp, int u) {
if (stp >= (1<<n)) return true;
int v = (u<<1)&((1<<n)-1);
if (!mrk[v]) {
mrk[v] = true;
if (DFS(stp+1, v))
return ans[stp] = 0, true;
mrk[v] = false;
}
v = (u<<1|1)&((1<<n)-1);
if (!mrk[v]) {
mrk[v] = true;
if (DFS(stp+1, v))
return ans[stp] = 1, true;
mrk[v] = false;
}
return false;
}
int main() {
read(n), DFS(0, 0), printf("%d ", 1<<n);
for (int i = 1; i < n; i++) putchar('0');
for (int i = 0; i <= (1<<n)-n; i++)
printf("%d", ans[i]);
return puts(""), 0;
}
------------- Thanks For Reading -------------
0%